/*
 * @name ajaxLib.js
 * @author : Amissah Gideon<kuulmek@yahoo.com>
 * @version 1.0
 */

Number.prototype.formatMoney = function (c, d, t) {
    var n = this, c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "," : d, t = t == undefined ? "." : t, s = n < 0 ? "-" : "", i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
    return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};


/*******************************************************************************
 *            COLLECTIONS CLASS
 ******************************************************************************/
function Collection(data) {
    this.list = {};
    this.size = 0;
    this.callbacks = {
        add:[],
        remove:[]
    };

    if (data) {
        var self = this;
        $.each(data, function (k, v) {
            self.add(k, v);
        });
    }
}

Collection.prototype.registerCallback = function (type, callback) {
    var self = this;
    if (typeof self.callbacks[type] != 'undefined') {
        self.callbacks[type].push(callback);
    }
}

Collection.prototype.fireCallbacks = function (type, key, value) {
    var self = this;
    for (var i = 0; i < self.callbacks[type].length; i++) {
        self.callbacks[type][i](key, value);
    }
}

/**
 * Adds a new object to the collection if the key for the object does not already exist
 * @param key the collection key
 * @param value the value to add
 **/
Collection.prototype.add = function (key, value) {
    var self = this;
    if (typeof self.list[key] == 'undefined') {
        self.list[key] = value;
        self.size++;

        self.fireCallbacks('add', key, value);
    }
    else {
        self.list[key] = value;
        self.fireCallbacks('add', key, value);
    }
}
/**
 * Removes the object identified by the key from the collection
 * @param key the search key
 **/
Collection.prototype.remove = function (key) {
    var self = this;
    if (typeof self.list[key] != 'undefined') {
        var value = self.list[key];
        delete self.list[key];
        self.size--;

        self.fireCallbacks('remove', key, value);
    }
}

/**
 * Returns the values stored for this key
 * @param key the search key
 **/
Collection.prototype.get = function (key) {
    var self = this;
    // if the a valid key is specified
    if (self.list.hasOwnProperty(key)) {
        return self.list[key];
    }
    // if the key specified is a number, then we may be looking for an element at a specified index
    if (!isNaN(parseInt(key))) {
        var index = 0;
        for (var k in self.list) {
            if (index == key) {
                return self.list[k];
            }
            index++;
        }
    }
    return null;
}

/**
 * Replaces or adds a new value to the map
 * @param key the key for the value
 * @param value the value to add
 */
Collection.prototype.set = function (key, value) {
    var self = this;
    self.list[key] = value;
}

/**
 * Returns the list of items stored in this collection
 * @return the list of items as an object
 */
Collection.prototype.getList = function () {
    var self = this;
    return self.list;
};

/**
 * Returns the count of the number items in this collection
 * @return number of items in this collection
 */
Collection.prototype.getSize = function () {
    var self = this;
    return self.size;
};

Collection.prototype.iterate = function (callback) {
    var self = this;
    for (var index in self.list) {
        if (typeof callback == "function") {
            callback.apply(self, [index, self.list[index]]);
        }
    }
};

Collection.prototype.getKeys = function () {
    var self = this;
    var keys = [];
    keys = Object.keys(self.list);
    return keys;
};

/**
 * Resets the list to an empty object
 */
Collection.prototype.clear = function () {
    var self = this;
    self.list = {};
    self.fireCallbacks('remove', null, null);
}

/*******************************************************************************
 *            END OF COLLECTIONS CLASS
 ******************************************************************************/



var jLib = {

    modal:null,

    /* Function init
     * This function is the entry point of the Object.
     * @param void
     * @return void
     * @access public
     * */
    init:function () {
        var self = this;
        $("#loader_bar").hide();
        /*Show a loading message whenever an Ajax request starts (and none is already active).*/
        $("#loader_bar").ajaxStart(function () {
            $(this).show();
        });

        $("#loader_bar").ajaxStop(function () {
            $(this).hide();
        });

        $('#feedback_bar').click(function () {
            $('#feedback_bar').fadeTo("fast", 0);
        });

        /** Toggle navigation contents**/
        $('#nav .nav_group ul li ul li a.navigate').click(function () {
            var $thisClass = $(this).attr('data-id');
            $('#nav .nav_group ul li ul li').each(function () {
                var a = $(this).find('a');
                var attr_class = $(a).attr('data-id');
                $('.' + attr_class).hide('slow');
            })

            $('.' + $thisClass).show('slow');

        });

        //For fixed table headers
        $("table.thfloat").thfloat({
            attachment:".thflotDiv"
        });

        //check if always hide
        if ($('#always-hide').attr('checked')) {
            //console.log('about to click')
            $('#open-menu').click();

            //console.log('clicked')
        }

        self.initAlwaysHide();
    },

    showFormLoading:function () {
        var self = this;
        self.modal = $.modal({
            contentAlign:'center',
            width:240,
            content:'<div style="line-height: 25px; padding: 0 0 10px"><span id="modal-status">Contacting server...</span><span id="modal-progress"></span></div>',
            buttons:{},
            scrolling:false,
            actions:{
                'Close':{
                    color:'red',
                    click:function (win) {
                        win.closeModal();
                    }
                }
            },
            onOpen:function () {
                // Progress bar
                var progress = $('#modal-progress').progress(100, {
                    size:200,
                    style:'large',
                    barClasses:['anthracite-gradient', 'glossy'],
                    stripes:true,
                    darkStripes:false,
                    showValue:false
                })
            }
        });
    },

    hideFormLoading:function () {
        var self = this;
        if (self.modal) {
            self.modal.closeModal();
        }
    },

    afterClosePopUpForm:function (form, callback) {
        var self = this;
        $(document).bind('cbox_closed', function () {
            document.getElementById(form).reset();
            $.validationEngine.closePrompt('.formError', true);
            if (typeof callback === 'function') {
                callback();
            }
        });
    },

    showModal:function () {
        var self = this;
        $('#modal_blanket').show();
    },

    hideModal:function () {
        var self = this;
        $('#modal_blanket').hide();
    },

    jalert:function (content, btn_color) {
        var self = this;

        if (!btn_color) {
            btn_color = 'grey';
        }

        $.modal({
            title:'Alert',
            content:content,
            buttons:{
                'Close':{
                    classes:btn_color + '-gradient glossy',
                    click:function (modal) {
                        modal.closeModal();
                    }
                }
            },
            buttonsAlign:'center'
        });
    },

    highlightRow:function (grid) {
        var self = this;
        $('.trSelected', grid).each(function () {
            $(this).removeClass('trSelected');
            var chk = $(this).find(':checkbox').is(':checked');
            if (chk) {
                $(this).find(':checkbox').attr('checked', false);
            }
            var has_class = false;
            if ($(this).hasClass('erow')) {
                $(this).removeClass('erow');
                has_class = true;
            }
            $(this).animate({backgroundColor:"#bbe4ff"}, "slow", "linear")
                .animate({backgroundColor:"#bbe4ff"}, 4000)
                .animate({backgroundColor:"#ffffff"}, "slow", "linear", function () {
                    // Animation complete.
                    if (has_class) {
                        $(this).addClass('erow');
                    }
                });
        });
        return;
    },

    updateGridData:function (grid, data) {
        var self = this;
        $('.trSelected', grid).each(function () {
            var tr = $(this);
            $(tr).find('td').each(function () {
                var val = data[$(this).attr('field')];
                if (typeof val != 'undefined') {
                    $(this).find('div').html(val);
                }
            })
        });
    },

    removeGridRows:function (grid) {
        var self = this;
        $('.trSelected', grid).each(function () {
            //$(this).removeClass('trSelected');
            $(this).animate({backgroundColor:"#bbe4ff"}, 1200, "linear")
                .animate({opacity:0}, 1200, "linear", function () {
                    $(this).remove();
                });
        });
    },

    countSelectedRows:function (grid) {
        var self = this;
        var selected_values = 0;
        $('.trSelected', grid).each(function () {
            selected_values = selected_values + 1;
        });
        return selected_values;
    },

    rowSelectedCheck:function (grid, limit) {
        var self = this;
        var count = jLib.countSelectedRows(grid);
        if (limit) {
            if (count < limit) {
                //jAlert("At least "+limit+" Record(s) needs to be selected prior to this action",'Alert');
                var content = "At least " + limit + " Record(s) needs to be selected prior to this action";
                self.jalert(content);
                return false;
            }
            else if (count > limit) {
                //jAlert("Only "+limit+" Record(s) at a time",'Alert');
                var content = "Only " + limit + " Record(s) at a time";
                self.jalert(content);
                return false;
            }
        }
        else {
            if (count == 0) {
                //jAlert("At least 1 Record needs to be selected prior to this action",'Alert');
                var content = "At least 1 Record needs to be selected prior to this action";
                self.jalert(content);
                return false;
            }
        }

        return true
    },

    getSelectedRowIds:function (grid) {
        var self = this;
        var selected_values = new Array();
        $('.trSelected', grid).each(function () {
            var id = $(this).attr('id');
            id = id.substring(id.lastIndexOf('row') + 3);
            selected_values.push(id);
        });
        return selected_values;
    },

    getSelectedRowColData:function (grid, col) {
        var self = this;
        var selected_values = new Array();
        $('.trSelected', grid).each(function () {
            $(this).find('td').each(function () {
                var field_value = $(this).attr('field');
                if (typeof field_value !== 'undefined' && field_value !== false && field_value == col) {
                    var content = $(this).find('div').html();
                    selected_values.push(content);
                }
            });
        });
        return selected_values;
    },

    getSelectedRows:function (grid) {
        var self = this;
        var selected_rows = new Array();
        $('.trSelected', grid).each(function () {
            selected_values.push($(this));
        });
        return selected_rows;
    },

    setFeedback:function (text, type, keep_displayed) {
        var self = this;
        var classname = 'color-block color-block-2';
        if (type == 'error_message') {
            classname = 'color-block color-block-1'
        }
        else if (type == 'warning_message') {
            classname = 'color-block color-block-3'
        }
        if (text != '') {
            $('#feedback_bar > div').removeClass();
            $('#feedback_bar > div').addClass(classname);
            $('#feedback_bar > div > .inside > span').text(text);
            $('#feedback_bar').css('opacity', '1');
            $('#feedback_bar').css('z-index', '2104');

            if (!keep_displayed) {
                $('#feedback_bar').fadeTo(5000, 1);
                $('#feedback_bar').fadeTo("fast", 0);
                $('#feedback_bar').css('z-index', '500');
            }
        }
        else {
            $('#feedback_bar').css('opacity', '0');
            $('#feedback_bar').css('z-index', '500');
        }
    },

    builPopUpPrompt:function (domObj, text, type, keep_displayed) {
        var self = this;
        $.validationEngine.buildPrompt(domObj, text, type);
        if (!keep_displayed) {
            setTimeout(function () {
                $.validationEngine.closePrompt('.formError', true)
            }, 5000);
        }

    },

    serverError:function (text) {
        var self = this;
        //first hide modal loader if any
        self.hideFormLoading();

        if (typeof text == 'undefined') {
            text = "Error while contacting server, please try again";
        }

        self.message(text, 'error');
    },


    menuAccordion:function (id) {
        var self = this;
        $('#' + id + ' ul > li ul')
            .click(function (e) {
                e.stopPropagation();
                $(this).parent().addClass("active");
            })
            .filter(':not(:first)')
            .hide();

        $('#' + id + ' ul > li').click(function () {
            var type = this;
            var selfClick = $(this).find('ul:first').is(':visible');
            if (!selfClick) {
                $(this)
                    .parent()
                    .find('> li ul:visible')
                    .slideToggle();
            }

            $(this)
                .find('ul:first')
                .stop(true, true)
                .slideToggle();

            $(this).addClass("active");
            $('#' + id + ' ul > li').each(function () {
                if (this != type) {
                    $(this).removeClass("active");
                }
            });

        });
    },


    /*Universal Delete for all jQuery DataTable*/
    do_delete:function (url, grid, callback) {
        var self = this;
        var row_ids = jLib.getSelectedRowIds(grid);

        $.modal.confirm('Are you sure you want to continue ?', function () {
            $.post(url, {'ids[]':row_ids}, function (response) {
                //delete was successful, remove checkbox rows
                if (response.code == 0) {
                    jLib.removeGridRows(grid);
                    self.message(response.mesg, 'success');

                    if (typeof callback == 'function') {
                        callback();
                    }
                }
                else if (response.code == 1) {
                    self.message(response.mesg, 'error');
                }
            }, "json");

        }, function () {
            //$.modal.alert('Meh.');
        });
    },

    //////////////////////Order General Functions
    array_diff:function (a1, a2) {
        var a = [], diff = [];
        for (var i = 0; i < a1.length; i++)
            a[a1[i]] = true;
        for (var i = 0; i < a2.length; i++)
            if (a[a2[i]]) delete a[a2[i]];
            else a[a2[i]] = true;
        for (var k in a)
            diff.push(k);
        return diff;
    },


    getRate:function ($rate, $tenor, $rate_decimal_places) {
        $rate = parseFloat($rate);
        $tenor = parseInt($tenor);
        $rate_decimal_places = parseInt($rate_decimal_places);
        var r = ($rate / 100) / ($tenor * 12); //interest rate per period
        r =  parseFloat(r.toFixed($rate_decimal_places));
        return  r;
    },

    getMonthlyPayment:function ($rate, $duration, $loan, $tenor, $rate_decimal_places,$purchase_type) {
        var self = this;

        var $A = 0;//payment Amount per period
        var $P = parseFloat($loan);//initial Principal (loan amount)
        var $r = self.getRate($rate, $tenor, $rate_decimal_places); //interest rate per period
        var $n = parseInt($duration);//total number of payments or periods

        if($purchase_type == 'Non Interest Payment'){
            //$A = $this->formatNumber($loan / $duration, 'number');
            $A = $P / $n;
        }
        else{
            var numerator = ($r * Math.pow((1 + $r), $n));
            var denuminator = (Math.pow((1 + $r), $n) - 1);
            var final = 0;
            if(numerator > 0 && denuminator > 0 ){
                final =  numerator / denuminator
            }
            $A = $P * (final);
        }


        //console.log(final);
        return $A;
    },

    get_amortization: function ($currency, $opening_bal, $duration_in_month, $interest,$tenor, $rate_decimal_places, $purchase_type) {
        var self = this;

        $opening_bal = parseFloat($opening_bal);
        $duration_in_month = parseInt($duration_in_month);
        $interest = parseFloat($interest);
        $tenor = parseInt($tenor);

        var $interest_ratio = self.getRate($interest, $tenor, $rate_decimal_places);
        //console.log($interest_ratio);
        var $mth_inst = self.getMonthlyPayment($interest, $duration_in_month, $opening_bal, $tenor ,$rate_decimal_places,$purchase_type);
       // console.log($mth_inst);
        // Building the amortization data
        var $new_opbl = $opening_bal;
       // console.log($new_opbl);
        var $amor = Array();

        var $row = Array();
        $row['period'] = '';
        $row['payment_amount'] = '';
        $row['inerest'] = '';
        $row['principal'] = '';
        $row['balance'] = $currency+" "+self.formatNumber($new_opbl, 'money');
        $amor.push($row);

        $tl_interest_paid = 0.00;
        $tl_principal = 0.00;

        for ($x = 1; $x <= $duration_in_month; $x++) {
            $payment_amount = $mth_inst;
            $inerest = $new_opbl * $interest_ratio;
            $principal = $payment_amount - $inerest;
            $balance = $bal1 = $new_opbl - $principal;
            $bal1 = self.formatNumber($bal1);

            if ($bal1 == -0.0) {
                $balance = 0.0;
            }

            $tl_interest_paid = $tl_interest_paid + $inerest;
            $tl_principal = $tl_principal + $principal;

            $row = Array();
            $row['period'] = $x;
            $row['payment_amount'] = self.formatNumber($mth_inst, 'money');
            $row['inerest'] = self.formatNumber($inerest, 'money');
            $row['principal'] = self.formatNumber($principal, 'money');
            $row['balance'] = self.formatNumber($balance, 'money');

            $amor.push($row);
            //Reset the new opening bal
            $new_opbl = $balance;
        }

        $json_data = Array();
        $json_data['data'] = $amor;
        $json_data['tl_inerest'] = self.formatNumber($tl_interest_paid, 'money');
        $json_data['tl_inerest_raw'] = self.formatNumber($tl_interest_paid);
        $json_data['tl_principal'] = self.formatNumber($tl_principal);
        $json_data['currency'] = $currency;
        $json_data['opening_bal'] = self.formatNumber($opening_bal, 'money');
        $json_data['opening_bal_raw'] = self.formatNumber($opening_bal);
        $json_data['duration_in_month'] = $duration_in_month;
        $json_data['interest_ratio'] = self.formatNumber($interest_ratio * 100);
        $json_data['monthly_inst'] = self.formatNumber($mth_inst, 'money');
        $json_data['monthly_inst_raw'] = self.formatNumber($mth_inst);

        return $json_data;
    },


    formatNumber:function ($value, $type, $decimal_place) {

        if (!$type) {
            $type = 'number';
        }
        if (!$decimal_place) {
            $decimal_place = 2;
        }
        var rt = 0.00;
        if ($type == 'money') {
            rt = parseFloat($value).formatMoney($decimal_place, '.', ',')
        }
        else {
            rt = parseFloat(parseFloat($value).toFixed($decimal_place));
        }

        return rt;
    },


    convertDate:function ($date, $type) {
        if ($date.length == 0) {
            return '';
        }
        var d = new Date($date);
        var $res = '';
        if ($type == 'mysql') {
            $res = d.toFormattedString('yyyy-MM-dd');
        }
        else if ($type == 'ui') {
            $res = d.toFormattedString('MMMM dd, yyyy');
        }
        return $res;
    },


    message:function (txt, type, callback) {
        var cl = '';
        if (type == 'success') {
            cl = 'green-gradient';
        }
        else if (type == 'warning') {
            cl = 'orange-gradient';
        }
        else if (type == 'error') {
            cl = 'red-gradient';
        }
        else if (type == 'info') {
            cl = 'blue-gradient';
        }
        else {
            cl = 'red-gradient';
        }

        var content = "<p class='message icon-speech " + cl + " small-margin-bottom'></span>" + txt + "</span></p>"

        $.modal({
            contentBg:false,
            contentAlign:'center',
            content:content,
            resizable:false,
            actions:{},
            buttons:{
                'Close':{
                    classes:cl,
                    click:function (modal) {
                        if (typeof callback == 'function') {
                            callback(modal);
                        }
                        else {
                            modal.closeModal();
                        }
                    }
                }
            },
            buttonsAlign:'center'
        });
    },


    notification:function (title, mesg, auto_close, show_icon) {
        var positionHorizontal = 'right', positionVertical = 'top',
            closeButton = true, showCloseOnHover = false;
        if (typeof show_icon == 'undefined') {
            show_icon = true;
        }

        if (typeof auto_close == 'undefined') {
            auto_close = true;
        }

        // Gather options
        notify(title, mesg, {
            system:false, //
            vPos:positionVertical,
            hPos:positionHorizontal,
            autoClose:auto_close,
            icon:(show_icon) ? $("#notification-user-src").val() : '',
            iconOutside:true,
            closeButton:closeButton,
            showCloseOnHover:showCloseOnHover,
            groupSimilar:true
        });
    },

    refreshCustomElement:function (element, type) {
        var self = this;
        if (type == 'select') {
            self.removeCustomSelect(element);
            self.applyCustomSelect(element);
        }
    },

    applyCustomSelect:function (element) {
        element.styleSelect();
    },

    removeCustomSelect:function (element) {
        var arrfunc = element.data('clearFunctions');

        for (var i = 0; i < arrfunc.length; i++) {
            arrfunc[i](element);
        }
    },

    initAlwaysHide:function () {
        var status = 'n';
        $('#always-hide').change(function () {
            if (this.checked) {
                status = 'y';
            }
            var url = $('#always-hide-url').val();
            var query = 'status=' + status;
            $.ajax({
                url:url,
                data:query,
                dataType:'json',
                type:'POST',
                success:function (response) {

                },
                error:function (xhr) {
                    console.log(xhr.responseText);
                    jLib.serverError();
                }
            });
        });
    }
};

/* when the page is loaded */
$(document).ready(function () {
    //Hiding the loader bar
    jLib.init();
});